package indi.simple.pms.handler;

import indi.simple.pms.constant.CommonConstant;
import indi.simple.pms.entity.viewobject.CommonResultVO;
import indi.simple.pms.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;

/**
 * @Author: wanglunhui
 * @Date: 2021/4/13 22:22
 * @Description: 全局返回和异常处理
 */
@RestControllerAdvice
@Slf4j
public class GlobalReturnAndErrorHandler /*extends SystemResultVO<?>ExceptionHandler*//*implements ResponseBodyAdvice<Object> */{
    /*@Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return body;
    }*/

    @ExceptionHandler(BadRequestException.class)
    public CommonResultVO<?> handleAuthorizationException(BadRequestException e) {
        return CommonResultVO.fail(e.getMessage());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public CommonResultVO<?> handlerNoFoundException(NoHandlerFoundException e) {
        return CommonResultVO.fail(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResultVO<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        FieldError fieldError=(FieldError)e.getBindingResult().getAllErrors().get(0);

        String field=fieldError.getField();
        String message=fieldError.getDefaultMessage();

        return CommonResultVO.fail(field+": "+message);
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public CommonResultVO<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e){
        return CommonResultVO.fail("参数类型不匹配, 参数: "+e.getName()+", 类型: "+e.getRequiredType().getSimpleName());
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public CommonResultVO<?> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException e){
        return CommonResultVO.fail("缺少参数, 参数: "+e.getParameterName()+", 类型: "+e.getParameterType());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public CommonResultVO<?> httpMessageNotReadableExceptionHandler(HttpMessageNotReadableException e){
        return CommonResultVO.fail("请传入请求体");
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public CommonResultVO<?> handlerConstraintViolationException(HttpServletRequest request, HttpServletResponse response, Throwable e) {
        return CommonResultVO.fail(e.getMessage());
    }

    @ExceptionHandler(AccessDeniedException.class)
    public CommonResultVO<?> handleAccessDeniedException(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) {
        return CommonResultVO.fail(403,e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public CommonResultVO<?> globalExceptionHandle(HttpServletRequest request, HttpServletResponse response, Throwable e) throws Exception {
        log.error(CommonConstant.ERROR_OCCUR,e);

        return CommonResultVO.fail(e.getMessage());
    }
}